Unity 2019.1的UIElements功能介绍
UIElements是Unity全新的保留模式UI框架,面向Unity 2019.1作为公开API发布。现在UIElements是一款可以轻松扩展Unity编辑器的工具,未来版本将加入游戏内支持和可视化制作功能。
你可以下载UIElements示例项目进行学习:
https://github.com/Unity-Technologies/UIElementsUniteLATurretDemo
过去,在Unity中构建自定义编辑器窗口和检视窗口意味着要使用即时模式API:IMGUI。
IMGUI可以帮助你轻松的构建用户界面,但是在构建较复杂的应用程序时会很难扩展。系统也很难优化渲染过程,因为用户可以随时在某一帧内大幅修改UI结构。
IMGUI的所有UI都通过C#代码声明,这意味着未来可视化制作UI的工具都会生成C#代码,这种做法很复杂。
UIElements作为保留模式API,它的核心思想是:用户构建出自己的UI对象层级,然后让系统进行渲染。通过这种方式,该系统可以优化绘制的内容和时间,从而实现更好的整体性能。
这种范例也允许用户把层级和样式从功能中分离,从而更好地分开关注点,为艺术家和程序员提供更易于理解的UI制作过程。
保留模式
UIElements的基本构造部分是VisualElement类,所有元素都是VisualElement或从中继承。独立的VisualElement可以互相嵌套,以形成UI层级。布局,样式和其它系统会遍历该层级,以便正确地渲染UI到屏幕上。
在编辑器中,每个EditorWindow都有一个rootVisualElement属性,该属性表示层级的顶部VisualElement。Element元素需要作为子对象添加到根对象上,从而让系统知道元素的信息,并进行绘制。
using UnityEditor;
using UnityEngine.UIElements;
public class ExampleWindow : EditorWindow
{
public void OnEnable()
{
var root = this.rootVisualElement;
IntSlider slider = new IntSlider();
root.Add(slider); // 添加滑块为根对象的子对象
}
}
只要元素处于层级之中,它会继续绘制,更新和消耗用户事件,而无需开发人员的输入。这就是保留模式和即时模式最大的不同之处,开发人员只需声明应该发生的事情和发生时间,不需要管理帧和帧之间的渲染。
为了停止绘制某个元素,例如这里的滑块,开发人员既可以通过样式变更,使它暂时无法看到,也可以把它从层级中永久移除。
// 轻松而动态地隐藏和显示元素
slider.style.display = Display.None;
// 该元素的工作已经完成,可以移除它了
slider.RemoveFromHierarchy();
保留模式也可以使用文档模型,让开发者分离层级(使用UXML)和样式(USS)声明为单独的资源。在C#代码中,你可以使用内置查询系统和事件系统,仅专注于绑定声明的UI和功能及数据。
通过为层级和样式使用分离的资源,可以可视化制作UI,可让所有用户在Unity中轻松调整、制作和设计UI。
可重用模板UXML
你可以完全使用C#代码组合元素层级,但和样式一样,大多数层级不会在UI的生命周期内有太大变化。因此建议模块化处理UI,定义层级为基于XML的独立资源,即UXML。
<UXML xmlns="UnityEngine.UIElements">
<VisualElement name="the-container">
<Label />
<SliderInt low-value="0" high-value="100" />
</VisualElement>
</UXML>
标签名称对应着C#类型,完全支持继承自VisualElement的用户定义类型。属性会在创建时在新元素上设置,嵌套的标签会成为父标签的子标签。
你可以像其它Unity资源一样加载.uxml资源,在过程中构造VisualTreeAsset对象,然后根据需要在任意元素下实例化或克隆VisualTreeAsset。
var uxml =
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/ExampleUI.uxml");
uxml.CloneTree(root); //在uxml中创建标签为根部分的子部分
下面将介绍如何使用查询系统通过UXML获取刚创建的元素。
共享样式USS
通过C#的属性可以直接在VisualElements上设置样式。虽然大部分样式会静态定义的,但它也可以在C#代码中分离描述和UI逻辑。
UIElements使用Unity专用的StyleSheet资源,称为USS,它使用CSS标准的子集。你可以使用和CSS代码相同的选择器,以识别哪些元素应该得到什么样式,样式本身是键值对。
/* 按照样式类 */
.standard-label {
padding: 6px;
}
/* 按照元素名称 */
#the-label {
font-size: 60px;
}
/* 按照C#类型 */
Label {
color: rgb(68, 255, 93);
}
你可以像其它Unity资源一样加载.uss资源,在过程中构造StyleSheet对象,然后指定它到所需的元素,它会自动应用其中的样式到该元素及其子元素上。
var uss = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/ExampleUI.uss");
root.styleSheets.Add(uss);
虽然样式可以根据名称属性或C#类型来应用,但为了更好的样式重用效果,你可以给元素指定一个或多个样式类,根据这些类在USS资源匹配样式,你可以把这些样式视为标签。
<!-- Assign a style class in UXML: -->
<Label />
// 在C#指定样式类
var label = new Label();
label.AddToClassList("blue-label");
你可以添加多个StyleSheets到相同元素,使用多个规则来匹配相同的元素。使用USS来设置复杂的重写规则,同时尽可能重复使用样式。
这样对共享样式进行迭代变成了很简单的事情,因为我们不必等待C#代码进行重新编译。StyleSheet(USS)资源的改动会在文件保存时自动应用到编辑器。
UQuery
UIElements中的查询系统叫UQuery,它和Web上的jQuery类似,允许你使用名称属性,当前指定的样式类列表和C#类型的组合来查找层级中的元素。
// 通过样式类和类型
var label = root.Q<Label>(className: "blue-label");
// 通过名称(它会返回VisualElement)
var container = root.Q("the-container");
你还可以创建Query对象以实现优化的重用效果,此时需要对动态层级多次运行查询过程。
// 构建一次查询
UQueryBuilder<SliderInt> query = root.Query<SliderInt>(classes: "blue-slider");
// 多次运行以获取更新结果
query.ForEach(slider => Debug.Log(slider.name));
事件
UIElements提供了一个事件系统。事件通常会发送到特定元素,然后在UI树的上下传播,直到使用完所有事件,但传播行为是可以定制的。
MouseMoveEvent等基本事件会由系统发送,你可以进行注册以接收事件,也可以定义和发送自定义用户事件。Event事件是了解UI中的状态何时变化或用户何时执行操作的主要方法。
下面的示例会检测用户何时改动滑块数值,然后在标签元素显示新的数值。
var label = new Label();
var slider = new SliderInt();
slider.RegisterCallback< ChangeEvent<int> >(evt =>
{
display.text = evt.newValue.ToString();
});
UIElements Debugger
如果UI出现问题,或是如果没有看到应该出现在屏幕的元素,你可以使用UIElements Debugger,该工具类似Chrome和Firefox里的网页调试工具。
使用UIElements Debugger调试UI的元素,可以启用Pick功能,把鼠标移动到元素上,或是右键单击元素并选择Inspect。UIElements Debugger会在左侧面板显示当前窗口的完整实时层级,在右侧面板显示样式检视窗口。
在样式检视窗口中,你可以查看什么样式指定到某个元素上,以及每个样式值来自什么地方,即在哪个StyleSheet资源和哪个选取器内。
最后,你可以实时添加和编辑样式值,在UI查看它们的效果。
其它功能
Bindings绑定
许多控制功能可以绑定到SerializedObjects,以链接UI和资源数据。任何实现IBindableinterface的元素,例如:所有内置字段都可以接收SerializedProperty的字符串绑定路径。然后你可以把元素层级通过 Bind()绑定到SerializedObjects。
IMGUIContainer
如果有许多使用IMGUI编写的编辑器UI,你可以使用特别的IMGUIContainer元素在UIElements UI中作为另一元素嵌入IMGUI UI。IMGUIContainer会获取用作OnGUI( )循环的回调,和正常情况一样从外部接收所有事件。
Scheduler调度工具
UIElements提供了一个简单的内置调度工具,你可以使用调度工具按一定时间延迟回调,然后以设定的间隔重复执行回调。
未来展望
我们正在开发UIElements对游戏内UI 的支持。此外,我们计划为UIElements提供可视化工作流程,让用户可以通过少量C#代码,甚至不使用C#代码来设计和构造可用的UI。
与此同时,Unity上越来越多的部分将使用UIElements构建,包括检视窗口,使用专用编辑器窗口的新工具和新工具栏。
我们会继续维护和改进IMGUI和UGUI,我们目前没有弃用它们的计划。尽管如此,UIElements将成为得到最多支持的推荐方法,用于在Unity构造UI,UIElements从Unity 2019.1开始在编辑器内使用。
更多Unity最新功能分享与技术讨论,尽在Unity Connect平台(Connect.unity.com)。下载Unity Connect APP,请点击此处。
推荐阅读
Unite Shanghai 2019
5月10日-12日上海,Unite大会即将开幕,仅剩最后2天购票通道即将关闭,购票即获指定Asset Store资源商店精品21款资源的5折优惠券。
活动报名:
大会信息:
购票请访问:Unite2019.csdn.net
点击“阅读原文”访问Unity Connect